package cn.jane.rpc.netty.client.stubs;

import cn.jane.rpc.netty.client.RequestIdSupport;
import cn.jane.rpc.netty.client.RpcRequest;
import cn.jane.rpc.netty.client.ServiceStub;
import cn.jane.rpc.netty.client.ServiceTypes;
import cn.jane.rpc.netty.serialize.SerializeSupport;
import cn.jane.rpc.netty.transport.Transport;
import cn.jane.rpc.netty.transport.command.Header;
import cn.jane.rpc.netty.transport.command.ResponseCode;
import cn.jane.rpc.netty.transport.command.Command;
import cn.jane.rpc.netty.transport.command.ResponseHeader;
import java.util.concurrent.ExecutionException;

/**
 * 桩对象的抽象父类
 */
public abstract class AbstractStub implements ServiceStub {

    protected Transport transport;

    /**
     * 进行 RPC
     *
     * @param request RPC 请求
     * @return RPC 结果
     */
    protected byte[] invokeRemote(RpcRequest request) {
        Header header = new Header(RequestIdSupport.next(), 1, ServiceTypes.TYPE_RPC_REQUEST);
        byte[] payload = SerializeSupport.serialize(request);
        Command requestCommand = new Command(header, payload);
        try {
            Command responseCommand = transport.send(requestCommand).get();
            ResponseHeader responseHeader = (ResponseHeader) responseCommand.getHeader();
            if (responseHeader.getCode() == ResponseCode.SUCCESS.getCode()) {
                // 如果调用成功，则返回负载
                return responseCommand.getPayload();
            } else {
                // 否则调用失败，抛出异常
                throw new Exception(responseHeader.getError());
            }
        } catch (ExecutionException e) {
            throw new RuntimeException(e.getCause());
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void setTransport(Transport transport) {
        this.transport = transport;
    }
}
